package com.besall.allbase.view.activity.chipstoollevel4.commandset;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.util.Log;

import androidx.core.app.ActivityCompat;

import com.bes.bessdk.service.base.BesServiceConfig;
import com.bes.bessdk.service.base.BesServiceListener;
import com.bes.bessdk.service.commandset.CommandSetService;
import bb.lanxing.R;
import com.besall.allbase.bluetooth.BluetoothConstants;
import com.besall.allbase.bluetooth.scan.ScanActivity;
import com.besall.allbase.common.utils.ActivityUtils;
import com.besall.allbase.view.base.BasePresenter;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Timer;
import java.util.TimerTask;


/**
 * @author ericshen
 * @time $ $
 */
class CommandSetPresenter extends BasePresenter<ICommandSetActivity> implements ICommandSetPresenter {
    CommandSetService commandSetService;
    static String TAG = "CommandSetPresenter";

    @Override
    public void pickDecice(CommandSetActivity context, int scan) {
        Intent intent = new Intent();
        intent.putExtra(BluetoothConstants.Scan.BES_SCAN, scan);
        ActivityUtils.gotoActForResult(intent, BluetoothConstants.Scan.REQUEST_CODE_SCAN, context, ScanActivity.class);
    }

    @Override
    public void connectDevice(BesServiceConfig serviceConfig, BesServiceListener listener, Context context) {
        commandSetService = new CommandSetService(serviceConfig, listener, context);
    }

    @Override
    public void sendTestData(Byte cmdType, boolean hasType, Byte...type) {
        Log.i(TAG, "sendTestData: ----------");
        if (commandSetService != null) {
            commandSetService.sendTestData(cmdType, hasType, type);
        }
    }

    @Override
    public void sendGetVersionCrcData() {
        if (commandSetService != null) {
            commandSetService.sendGetVersionCrcData();
        }
    }

    @Override
    public void stopSpp() {
        if (commandSetService != null) {
            commandSetService.disconnected();
        }
    }

    @Override
    public int getBtState() {
        BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
        int a2dp = mAdapter.getProfileConnectionState(BluetoothProfile.A2DP); // 可操控蓝牙设备，如带播放暂停功能的蓝牙耳机
        int headset = mAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); // 蓝牙头戴式耳机，支持语音输入输出
        if (a2dp == BluetoothProfile.STATE_CONNECTED && headset == BluetoothProfile.STATE_CONNECTED) {
            return 1;
        }
        return 0;
    }

    @Override
    public void startPlayVideoWithType(Context context, int type, MediaPlayer.OnCompletionListener mediaListener) {
        AudioManager audioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
        audioManager.stopBluetoothSco();
        audioManager.setBluetoothScoOn(false);

        MediaPlayer mp = MediaPlayer.create(context.getApplicationContext(), R.raw.speaker_test_video);
        mp.setVolume(type == 0 ? 1 : 0, type == 0 ? 0 : 1);
        mp.setOnCompletionListener(mediaListener);
        mp.start();
    }

    @Override
    public void checkMicState(Activity activity, Context context, CheckMicStateListener listener) {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
            return;
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                openSco(context, listener);
            }
        }).start();

        timeCount = 0;
        timeTimer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                timeCount ++;
                Log.i(TAG, "timeCount: ---------" + timeCount);
                if (timeCount > 20) {
                    stopTimer();
                    stopSco(context);
                    listener.onMicStateChanged(11, "Not enough sound was collected");
                }
            }
        };
        timeTimer.schedule(task, 1000, 1000);
    }

    AudioManager mAudioManager;
    int frequency = 44100;
    boolean isPlaying = false;
    int micReceiveDtaCount = 0;
    Thread micThread;
    Timer timeTimer;
    TimerTask task;
    int timeCount = 0;

    private void openSco(Context context, CheckMicStateListener listener) {
        micReceiveDtaCount = 0;
        mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
        int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
        int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
        int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration, audioEncoding);

        if(!mAudioManager.isBluetoothScoAvailableOffCall()){
            listener.onMicStateChanged(11, "The system does not support Bluetooth recording");
            return;
        }
        mAudioManager.setBluetoothScoOn(true);
        mAudioManager.startBluetoothSco();
        context.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
                if (AudioManager.SCO_AUDIO_STATE_CONNECTED == state) {
                    Log.i(TAG, "onReceive: ----------打开SCO");
                    mAudioManager.setBluetoothScoOn(true);  //打开SCO
                    AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channelConfiguration, audioEncoding, bufferSize);
                    if (audioRecord.getState() == 1) {
                        audioRecord.startRecording();
                        isPlaying = true;
                        micThread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                while (isPlaying) {
                                    byte[] buffer = new byte[bufferSize];
                                    int readBytes = audioRecord.read(buffer, 0, bufferSize);
                                    if (readBytes > 0) {
                                        int valume = calculateVolume(buffer);
                                        Log.i(TAG, "valume: --------" + valume);
                                        if (valume > 50) {
                                            micReceiveDtaCount ++;
                                            listener.onMicStateChanged(1, micReceiveDtaCount + "");
                                            if (micReceiveDtaCount > 99) {
                                                listener.onMicStateChanged(0, "");
                                                audioRecord.stop();
                                                stopTimer();
                                                stopSco(context);
                                            }
                                        }
                                    } else {
                                        Log.i(TAG, "valume=0");
                                    }
//                                    if ((ArrayUtil.toHex(buffer).contains("ff,ff,ff,ff,ff,ff,ff,ff")) || (ArrayUtil.toHex(buffer).contains("00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00"))) {
//
//                                    } else {
//                                        micReceiveDtaCount ++;
//                                        Log.i(TAG, "run: ------" + micReceiveDtaCount);
//                                        listener.onMicStateChanged(1, micReceiveDtaCount + "");
//                                        if (micReceiveDtaCount > 99) {
//                                            listener.onMicStateChanged(0, "");
//                                            audioRecord.stop();
//                                            stopTimer();
//                                            stopSco(context);
//                                        }
//                                    }
                                }
                            }
                        });
                        micThread.start();
                    }
                    context.unregisterReceiver(this);
                } else {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    mAudioManager.startBluetoothSco();
                }
            }
        }, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
    }

    int calculateVolume(byte[] buffer) {
        short[] audioData = new short[buffer.length / 2];
        ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(audioData);
        double sum = 0.0;
        for (int i = 0; i < audioData.length; i ++) {
            sum += (audioData[i] * audioData[i]);
        }
        double mean = sum / audioData.length;
        double volume = 10 * Math.log10(mean);

        return (int) volume;
    }

    void stopSco(Context context) {
        Log.i(TAG, "stopSco: --------");
        mAudioManager.stopBluetoothSco();
        mAudioManager.setBluetoothScoOn(false);
        isPlaying = false;
        new Thread(new Runnable() {
            @Override
            public void run() {
                mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
                mAudioManager.stopBluetoothSco();
                mAudioManager.setBluetoothScoOn(false);
            }
        }).start();
    }

    void stopTimer() {
        if (timeTimer != null) {
            timeTimer.cancel();
            timeTimer = null;
        }
    }
}
